package com.java.core.memorymap;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.CRC32;

/**
 * @Author YongQiang
 * @Date 2021/10/8 16:38
 * @Version 1.0
 */
public class MemoryMapTest {
    public static void main(String[] args) throws IOException {
        String path = "D:\\java\\jdk1.8\\jre\\lib\\rt.jar";
        Path fileName = Paths.get(path);

        long start = 0L,crcValue = 0L,end=0L;


        System.out.println("Input Stream...");
        start = System.currentTimeMillis();
        crcValue = checkSumInputStream(fileName);
        end = System.currentTimeMillis();
        System.out.println("计算时间:" + (end - start) + " ms, crcValue:" + crcValue);

        System.out.println("Buffer Stream...");
        start = System.currentTimeMillis();
        crcValue = checkSumBufferedInputStream(fileName);
        end = System.currentTimeMillis();
        System.out.println("计算时间:" + (end - start) + " ms, crcValue:" + crcValue);

        System.out.println("RandomAccess File...");
        start = System.currentTimeMillis();
        crcValue = checkSumRandomAccessFile(fileName);
        end = System.currentTimeMillis();
        System.out.println("计算时间:" + (end - start) + " ms, crcValue:" + crcValue);

        System.out.println("memory Map...");
        start = System.currentTimeMillis();
        crcValue = checkSumMappedFile(fileName);
        end = System.currentTimeMillis();
        System.out.println("计算时间:" + (end - start) + " ms, crcValue:" + crcValue);

    }


    /**
     * 普通输入流
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static long checkSumInputStream(Path fileName) throws IOException {
        try (InputStream inputStream = Files.newInputStream(fileName)) {
            CRC32 crc32 = new CRC32();
            int c;
            while ((c = inputStream.read()) != -1) {
                crc32.update(c);
            }
            return crc32.getValue();
        }
    }

    /**
     * 带缓冲的输入流
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static long checkSumBufferedInputStream(Path fileName) throws IOException {
        try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(fileName))) {
            CRC32 crc32 = new CRC32();
            int c;
            while ((c = inputStream.read()) != -1) {
                crc32.update(c);
            }
            return crc32.getValue();
        }
    }

    /**
     * 随机访问文件
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static long checkSumRandomAccessFile(Path fileName) throws IOException {
        try (RandomAccessFile file = new RandomAccessFile(fileName.toFile(), "r")) {
            CRC32 crc32 = new CRC32();
            long length = file.length();
            for (long p = 0; p < length; p++) {
                file.seek(p);
                int b = file.readByte();
                crc32.update(b);
            }
            return crc32.getValue();
        }
    }

    /**
     * 内存映射文件
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static long checkSumMappedFile(Path fileName) throws IOException {
        try (FileChannel channel = FileChannel.open(fileName)) {
            CRC32 crc32 = new CRC32();
            long length = channel.size();
            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, length);
            for (int p = 0; p < length; p++) {
                int b = buffer.get(p);
                crc32.update(b);
            }
            return crc32.getValue();
        }
    }
}
